package com.cx.util;

import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.SerializationUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;

import java.io.*;
import java.lang.invoke.SerializedLambda;

/**
 * @author cxx
 * @create 2021-03-24 14:15
 **/
public class LambdaTest {



    public class Demo{
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) {
//        com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda serializedLambda = LambdaUtils.resolve (Demo::getName);
//        System.out.println (serializedLambda);
        com.cx.util.SerializedLambda  serializedLambda = resolve (Demo::getName);
        System.out.println (serializedLambda);



    }

//    public static <T> SerializedLambda resolve(IFunction<T, ?> lambda) {
//        if (!lambda.getClass().isSynthetic()) {
//            throw new RuntimeException ("该方法仅能传入 lambda 表达式产生的合成类");
//        }
//        try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream (serialize(lambda))) {
//            @Override
//            protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
//                Class<?> clazz = super.resolveClass(objectStreamClass);
//                return clazz;
//            }
//        }) {
//            return (SerializedLambda) objIn.readObject();
//        } catch (ClassNotFoundException | IOException e) {
//            e.printStackTrace ();
//
//        }
//        return null;
//    }

    public static <T> com.cx.util.SerializedLambda  resolve(SFunction<T, ?> lambda) {
        System.out.println (lambda);
        if (!lambda.getClass().isSynthetic()) {
            throw ExceptionUtils.mpe("该方法仅能传入 lambda 表达式产生的合成类");
        }
        try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) {
            @Override
            protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
                Class<?> clazz = super.resolveClass(objectStreamClass);
                return clazz == java.lang.invoke.SerializedLambda.class ? com.cx.util.SerializedLambda .class : clazz;
            }

            @Override
            protected Object resolveObject(Object obj) throws IOException {
                return super.resolveObject (obj);
            }
        }) {
            return (com.cx.util.SerializedLambda ) objIn.readObject();
        } catch (ClassNotFoundException | IOException e) {
            throw ExceptionUtils.mpe("This is impossible to happen", e);
        }
    }


//    public static <T> SerializedLambda resolve(SFunction<T, ?> lambda) {
//        if (!lambda.getClass().isSynthetic()) {
//            throw ExceptionUtils.mpe("该方法仅能传入 lambda 表达式产生的合成类");
//        }
//        try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) {
//            @Override
//            protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
//                Class<?> clazz = super.resolveClass(objectStreamClass);
//                return clazz;
//            }
//        }) {
//            return (SerializedLambda) objIn.readObject();
//        } catch (ClassNotFoundException | IOException e) {
//            throw ExceptionUtils.mpe("This is impossible to happen", e);
//        }
//    }


    public static byte[] serialize(Object object) {
        if (object == null) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
        try {
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            oos.flush();
        } catch (IOException ex) {
            throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
        }
        return baos.toByteArray();
    }
}
